#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
系统指令执行器

根据解析后的指令执行具体的系统操作
"""

import os
import subprocess
import platform
import json
import time
from typing import Dict, List, Optional, Any

# 处理相对导入和直接运行的兼容性
try:
    from .llm_client import LLMClient
    from .amap_command_handler import AmapCommandHandler
except ImportError:
    from llm_client import LLMClient
    from amap_command_handler import AmapCommandHandler


class CommandExecutor:
    """
    系统指令执行器
    执行各种系统操作，如音乐播放、文件操作等
    """
    
    def __init__(self):
        """初始化执行器"""
        self.system = platform.system().lower()
        self.llm_client = LLMClient()
        
        # 初始化地图命令处理器
        self.amap_handler = AmapCommandHandler()
        
        # 系统特定的应用程序映射
        self.app_mappings = {
            "darwin": {  # macOS
                "音乐软件": ["Music", "Spotify", "QQ音乐", "网易云音乐"],
                "文本编辑器": ["TextEdit", "Visual Studio Code", "Sublime Text", "Atom"],
                "记事本": ["TextEdit"],
                "浏览器": ["Safari", "Google Chrome", "Firefox"],
                "终端应用": ["Terminal", "iTerm2", "Terminal.app"]
            },
            "windows": {  # Windows
                "音乐软件": ["Windows Media Player", "Spotify", "QQ音乐", "网易云音乐"],
                "文本编辑器": ["notepad", "Visual Studio Code", "Sublime Text", "Atom"],
                "记事本": ["notepad"],
                "浏览器": ["chrome", "firefox", "edge"],
                "终端应用": ["cmd", "powershell", "Windows Terminal"]
            },
            "linux": {  # Linux
                "音乐软件": ["rhythmbox", "spotify", "audacious"],
                "文本编辑器": ["gedit", "vim", "nano", "code"],
                "记事本": ["gedit", "nano"],
                "浏览器": ["firefox", "chromium", "chrome"],
                "终端应用": ["gnome-terminal", "konsole", "xterm", "terminator"]
            }
        }
    
    def execute_command(self, parsed_command: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行解析后的指令
        
        Args:
            parsed_command: 解析后的指令对象
            
        Returns:
            执行结果
        """
        try:
            intent = parsed_command.get("intent")
            action = parsed_command.get("action")
            parameters = parsed_command.get("parameters", {})
            
            print(f"🚀 开始执行指令: {intent} -> {action}")
            
            # 根据意图分发到不同的执行器
            if intent == "music":
                return self._execute_music_command(action, parameters)
            elif intent == "file":
                return self._execute_file_command(action, parameters)
            elif intent == "alarm":
                return self._execute_alarm_command(action, parameters)
            elif intent == "system":
                return self._execute_system_command(action, parameters)
            elif intent == "map":
                return self._execute_map_command(action, parameters)
            # elif intent == "ai_generation":
            #     return self._execute_ai_generation_command(action, parameters)
            else:
                return self._create_error_result(f"不支持的指令类型: {intent}")
                
        except Exception as e:
            print(f"❌ 指令执行失败: {e}")
            return self._create_error_result(f"执行过程中发生错误: {str(e)}")
    
    def _execute_music_command(self, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """执行音乐相关指令"""
        try:
            if action == "play":
                song_name = parameters.get("song_name")
                artist = parameters.get("artist")
                original_text = parameters.get("original_text")
                
                # 显示推测信息
                if original_text and original_text != song_name:
                    print(f"🎵 智能推测: '{original_text}' → '{song_name}'")
                
                # 首先尝试打开音乐应用
                music_app_result = self._open_music_app()
                
                if song_name:
                    # 构建搜索和播放的AppleScript (macOS) 或其他系统命令
                    if self.system == "darwin":
                        return self._play_music_macos(song_name, artist, original_text)
                    elif self.system == "windows":
                        return self._play_music_windows(song_name, artist)
                    else:
                        return self._play_music_linux(song_name, artist)
                else:
                    return music_app_result
                    
            elif action in ["pause", "stop", "next", "previous"]:
                return self._control_music_playback(action)
            else:
                return self._create_error_result(f"不支持的音乐操作: {action}")
                
        except Exception as e:
            return self._create_error_result(f"音乐指令执行失败: {str(e)}")
    
    def _execute_file_command(self, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """执行文件操作指令"""
        try:
            if action == "create":
                return self._create_file(parameters)
            elif action == "open":
                return self._open_file(parameters)
            elif action == "save":
                return self._save_file(parameters)
            elif action == "delete":
                return self._delete_file(parameters)
            else:
                return self._create_error_result(f"不支持的文件操作: {action}")
                
        except Exception as e:
            return self._create_error_result(f"文件操作失败: {str(e)}")
    
    def _execute_alarm_command(self, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """执行闹钟相关指令"""
        try:
            if action == "set":
                return self._set_alarm(parameters)
            elif action == "list":
                return self._list_alarms()
            elif action == "cancel":
                return self._cancel_alarm(parameters)
            else:
                return self._create_error_result(f"不支持的闹钟操作: {action}")
                
        except Exception as e:
            return self._create_error_result(f"闹钟操作失败: {str(e)}")
    
    def _open_music_app(self) -> Dict[str, Any]:
        """打开音乐应用"""
        try:
            music_apps = self.app_mappings.get(self.system, {}).get("音乐软件", [])
            
            for app in music_apps:
                if self._try_open_app(app):
                    return self._create_success_result(f"成功打开音乐应用: {app}")
            
            return self._create_error_result("无法找到或打开音乐应用")
            
        except Exception as e:
            return self._create_error_result(f"打开音乐应用失败: {str(e)}")
    
    def _play_music_macos(self, song_name: str, artist: str = None, original_text: str = None) -> Dict[str, Any]:
        """在macOS上播放音乐"""
        try:
            # 使用AppleScript控制Music应用
            search_term = f"{song_name}"
            if artist:
                search_term = f"{artist} {song_name}"
            
            # 如果有原始文本，记录推测信息
            if original_text and original_text != song_name:
                print(f"🔍 搜索推测后的歌名: {search_term} (原始: {original_text})")
            else:
                print(f"🔍 搜索歌曲: {search_term}")
            
            # 改进的AppleScript - 使用多种搜索策略
            applescript = f'''
            tell application "Music"
                activate
                try
                    -- 策略1: 精确搜索完整关键词
                    set searchResults to (search library playlist 1 for "{search_term}")
                    if (count of searchResults) > 0 then
                        play (item 1 of searchResults)
                        return "正在播放: " & name of (item 1 of searchResults) & " - " & artist of (item 1 of searchResults)
                    end if
                    
                    -- 策略2: 搜索歌曲名
                    if "{song_name}" is not "" then
                        set searchResults to (search library playlist 1 for "{song_name}")
                        if (count of searchResults) > 0 then
                            play (item 1 of searchResults)
                            return "正在播放: " & name of (item 1 of searchResults) & " - " & artist of (item 1 of searchResults) & " (通过歌名匹配)"
                        end if
                    end if
                    
                    -- 策略3: 模糊匹配歌曲名（包含关键词）
                    set allTracks to every track of library playlist 1
                    set foundTrack to missing value
                    
                    -- 先尝试匹配带歌手名的
                    repeat with aTrack in allTracks
                        set trackName to name of aTrack
                        set trackArtist to artist of aTrack
                        if trackName contains "{song_name}" then
                            if "{artist}" is not "" then
                                if trackArtist contains "{artist}" then
                                    set foundTrack to aTrack
                                    exit repeat
                                end if
                            else
                                set foundTrack to aTrack
                                exit repeat
                            end if
                        end if
                    end repeat
                    
                    if foundTrack is not missing value then
                        play foundTrack
                        return "正在播放: " & name of foundTrack & " - " & artist of foundTrack & " (模糊匹配)"
                    end if
                    
                    -- 策略4: 如果指定了歌曲名，不走歌手降级，直接去在线搜索
                    -- 只有当用户只说了歌手名（没有歌曲名）时，才播放该歌手的任意歌曲
                    if "{song_name}" is "" and "{artist}" is not "" then
                        -- 用户只说了歌手，播放该歌手的任意歌曲
                        repeat with aTrack in allTracks
                            if artist of aTrack contains "{artist}" then
                                play aTrack
                                return "正在播放: " & name of aTrack & " - " & artist of aTrack & " (歌手匹配)"
                            end if
                        end repeat
                    end if
                    
                    -- 策略5: 本地资料库未找到指定歌曲，尝试从 Apple Music 在线搜索
                    return "NOT_FOUND_IN_LIBRARY:{search_term}"
                on error errorMessage
                    -- 如果搜索失败，尝试简单的播放命令
                    try
                        play
                        return "已开始播放音乐"
                    on error
                        return "音乐播放出错: " & errorMessage
                    end try
                end try
            end tell
            '''
            
            # 调试日志：显示执行的AppleScript命令参数
            print(f"🔧 [调试] 执行音乐搜索:")
            print(f"   搜索关键词: {search_term}")
            print(f"   歌曲名: {song_name}")
            print(f"   歌手: {artist}")
            
            # 保存AppleScript到可执行脚本文件（每次覆盖）
            # debug_script_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "last_applescript.applescript")
            # try:
            #     with open(debug_script_path, 'w', encoding='utf-8') as f:
            #         # 添加注释说明（AppleScript注释格式）
            #         f.write("-- " + "=" * 76 + "\n")
            #         f.write(f"-- 执行时间: {self._get_current_time()}\n")
            #         f.write(f"-- 搜索关键词: {search_term}\n")
            #         f.write(f"-- 歌曲名: {song_name}\n")
            #         f.write(f"-- 歌手: {artist}\n")
            #         f.write("-- " + "=" * 76 + "\n")
            #         f.write(f"-- 终端执行方式: osascript {debug_script_path}\n")
            #         f.write("-- " + "=" * 76 + "\n\n")
            #         f.write(applescript)
            #
            #     # 设置文件为可执行
            #     os.chmod(debug_script_path, 0o755)
            #     print(f"📝 [调试] AppleScript已保存到: {debug_script_path}")
            #     print(f"💡 [调试] 终端执行命令: osascript {debug_script_path}")
            # except Exception as e:
            #     print(f"⚠️ [调试] 保存AppleScript失败: {e}")
            
            result = subprocess.run(
                ["osascript", "-e", applescript],
                capture_output=True,
                text=True,
                timeout=15
            )
            
            # 调试日志：显示执行结果
            print(f"🔧 [调试] AppleScript返回码: {result.returncode}")
            print(f"🔧 [调试] 标准输出: {result.stdout.strip()}")
            if result.stderr:
                print(f"🔧 [调试] 标准错误: {result.stderr.strip()}")
            
            if result.returncode == 0:
                output = result.stdout.strip()
                
                # 检查是否本地库未找到，需要在线搜索
                if output.startswith("NOT_FOUND_IN_LIBRARY:"):
                    search_query = output.replace("NOT_FOUND_IN_LIBRARY:", "")
                    print(f"📡 本地资料库未找到，尝试从 Apple Music 在线搜索: {search_query}")
                    
                    # 尝试打开 Apple Music 在线搜索
                    return self._search_apple_music_online(search_query, song_name, artist, original_text)
                
                elif "出错" in output or "未找到" in output:
                    # 如果没找到，提供有帮助的错误信息和建议
                    error_msg = f"未找到歌曲"
                    
                    # 显示搜索的歌曲名
                    if original_text and original_text != song_name:
                        error_msg += f" '{song_name}' (推测自 '{original_text}')"
                    else:
                        error_msg += f" '{song_name}'"
                    
                    if artist:
                        error_msg += f" - {artist}"
                    
                    # 提供建议
                    error_msg += "\n\n可能的原因："
                    error_msg += "\n1. 歌曲不在您的Apple Music音乐库中"
                    error_msg += "\n2. 歌曲名称可能不完整或有误"
                    error_msg += f"\n3. 请尝试说完整歌名或直接说 '播放{artist}的歌'"
                    
                    print(f"⚠️ {error_msg}")
                    return self._create_error_result(error_msg)
                else:
                    success_msg = f"{output}"
                    if original_text and original_text != song_name:
                        success_msg += f" (推测自 '{original_text}')"
                    return self._create_success_result(success_msg)
            else:
                # 如果AppleScript失败，尝试简单的打开Music应用
                try:
                    print(f"🔧 [调试] 执行命令: open -a Music")
                    subprocess.run(["open", "-a", "Music"], check=True, timeout=5)
                    return self._create_success_result(f"已打开Music应用，请手动搜索: {search_term}")
                except:
                    return self._create_error_result(f"无法打开Music应用")
                
        except subprocess.TimeoutExpired:
            return self._create_error_result("音乐播放超时")
        except Exception as e:
            return self._create_error_result(f"macOS音乐播放失败: {str(e)}")
    
    def _search_apple_music_online(self, search_query: str, song_name: str, artist: str = None, original_text: str = None) -> Dict[str, Any]:
        """从 Apple Music 在线搜索歌曲"""
        try:
            print(f"🌐 尝试在 Music.app 中搜索 Apple Music: {search_query}")
            
            # 方案1: 使用剪贴板 + GUI 自动化在 Music.app 中搜索（支持中文）
            # keystroke 对中文支持不好，所以使用剪贴板粘贴
            applescript = f'''
-- 保存当前剪贴板内容（备份）
set oldClipboard to the clipboard

-- 将搜索关键词复制到剪贴板
set the clipboard to "{search_query}"

tell application "Music"
    activate
end tell

delay 0.5

tell application "System Events"
    tell process "Music"
        -- 确保窗口已打开
        if not (exists window 1) then
            tell application "Music" to activate
            delay 0.3
        end if
        
        -- 使用快捷键 Cmd+F 打开搜索框
        keystroke "f" using command down
        delay 0.3
        
        -- 全选现有内容并删除（如果有）
        keystroke "a" using command down
        delay 0.1
        
        -- 使用 Cmd+V 粘贴搜索关键词（支持中文）
        keystroke "v" using command down
        delay 0.5
        
        -- 按回车开始搜索
        keystroke return
        
        -- 等待搜索结果加载
        delay 2.0
        
        -- 关键步骤：按 Escape 键退出搜索框
        key code 53 -- Escape
        delay 1.0
        
        -- 按 3 次 Tab 键定位到第一条搜索结果（关键：需要 3 次）
        keystroke tab
        keystroke tab
        keystroke tab
        delay 0.3
        
        -- 按 Return 进入专辑并自动播放
        keystroke return
    end tell
end tell

-- 恢复原来的剪贴板内容
delay 0.3
set the clipboard to oldClipboard

return "已在 Music.app 中搜索并开始播放：{search_query}"
            '''
            
            # 保存在线搜索脚本
            # debug_script_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "last_online_search.applescript")
            # try:
            #     with open(debug_script_path, 'w', encoding='utf-8') as f:
            #         f.write(f"-- Apple Music 在线搜索并自动播放（GUI自动化）\n")
            #         f.write(f"-- 搜索关键词: {search_query}\n")
            #         f.write(f"-- \n")
            #         f.write(f"-- ✅ 成功的执行流程（经过实际测试）:\n")
            #         f.write(f"--   1. Cmd+F - 打开搜索框\n")
            #         f.write(f"--   2. Cmd+A - 全选搜索框\n")
            #         f.write(f"--   3. Cmd+V - 粘贴搜索词（支持中文）\n")
            #         f.write(f"--   4. Return - 开始搜索\n")
            #         f.write(f"--   5. Escape - 退出搜索框\n")
            #         f.write(f"--   6. Tab × 3 - 定位到第一条搜索结果（需要按3次）✨\n")
            #         f.write(f"--   7. Return - 进入专辑并自动播放 🎵\n")
            #         f.write(f"-- \n")
            #         f.write(f"-- 注意: 需要在系统设置中授予辅助功能权限\n\n")
            #         f.write(applescript)
            #     os.chmod(debug_script_path, 0o755)
            #     print(f"📝 [调试] 在线搜索脚本已保存到: {debug_script_path}")
            # except:
            #     pass
            
            result = subprocess.run(
                ["osascript", "-e", applescript],
                capture_output=True,
                text=True,
                timeout=15
            )
            
            if result.returncode == 0:
                output = result.stdout.strip()
                success_msg = f"🎵 已从 Apple Music 搜索并开始播放：{search_query}\n"
                success_msg += "💡 提示：\n"
                success_msg += "  • 已自动选择并播放搜索结果的第一首歌曲\n"
                success_msg += "  • 如果想添加到资料库，在 Music.app 中点击 '+' 按钮\n"
                success_msg += "  • 添加后，下次就能从本地资料库直接播放了"
                
                print(f"✅ {success_msg}")
                return self._create_success_result(success_msg)
            else:
                # GUI 自动化可能失败（权限问题），降级到浏览器方案
                import urllib.parse
                encoded_query = urllib.parse.quote(search_query)
                apple_music_url = f"https://music.apple.com/cn/search?term={encoded_query}"
                
                print(f"⚠️ GUI 自动化失败（可能需要辅助功能权限），降级到浏览器方案")
                print(f"🔧 [降级] 打开浏览器搜索: {apple_music_url}")
                
                subprocess.run(["open", apple_music_url], check=True)
                
                fallback_msg = f"已在浏览器中打开 Apple Music 搜索：{search_query}\n"
                fallback_msg += "💡 提示：找到歌曲后，添加到资料库即可语音播放\n\n"
                fallback_msg += "⚠️ 如需在 Music.app 中直接搜索，请在系统设置中授予辅助功能权限：\n"
                fallback_msg += "  系统设置 → 隐私与安全性 → 辅助功能 → 添加 Terminal（或你的Python应用）"
                
                return self._create_success_result(fallback_msg)
                
        except Exception as e:
            print(f"❌ Apple Music 在线搜索失败: {e}")
            error_msg = f"本地资料库未找到歌曲 '{song_name}'"
            if artist:
                error_msg += f" - {artist}"
            error_msg += "\n\n💡 建议：请手动在 Apple Music 中搜索并添加到资料库"
            return self._create_error_result(error_msg)
    
    def _play_music_windows(self, song_name: str, artist: str = None) -> Dict[str, Any]:
        """在Windows上播放音乐"""
        # Windows实现 - 可以使用Windows Media Player或其他音乐应用的API
        return self._create_success_result(f"Windows音乐播放功能正在开发中，搜索: {song_name}")
    
    def _play_music_linux(self, song_name: str, artist: str = None) -> Dict[str, Any]:
        """在Linux上播放音乐"""
        # Linux实现 - 可以使用rhythmbox或其他音乐播放器
        return self._create_success_result(f"Linux音乐播放功能正在开发中，搜索: {song_name}")
    
    def _control_music_playback(self, action: str) -> Dict[str, Any]:
        """控制音乐播放"""
        try:
            if self.system == "darwin":
                applescript_commands = {
                    "pause": "pause",
                    "stop": "stop",
                    "next": "next track",
                    "previous": "previous track"
                }
                
                command = applescript_commands.get(action)
                if command:
                    applescript = f'tell application "Music" to {command}'
                    print(f"🔧 [调试] 执行AppleScript: osascript -e 'tell application \"Music\" to {command}'")
                    result = subprocess.run(
                        ["osascript", "-e", applescript],
                        capture_output=True,
                        text=True,
                        timeout=5
                    )
                    print(f"🔧 [调试] 返回码: {result.returncode}, 输出: {result.stdout.strip()}")
                    
                    if result.returncode == 0:
                        return self._create_success_result(f"音乐控制成功: {action}")
                    else:
                        return self._create_error_result(f"音乐控制失败: {result.stderr}")
            
            return self._create_success_result(f"音乐控制: {action} (其他系统功能开发中)")
            
        except Exception as e:
            return self._create_error_result(f"音乐控制失败: {str(e)}")
    
    def _create_file(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """创建文件"""
        try:
            file_path = parameters.get("file_path") or parameters.get("file_name", "新建文件.txt")
            content = parameters.get("content", "")
            
            # 如果只提供了文件名，创建在桌面
            if not os.path.dirname(file_path):
                desktop = os.path.join(os.path.expanduser("~"), "Desktop")
                file_path = os.path.join(desktop, file_path)
            
            # 确保目录存在
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
            
            # 创建文件
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)
            
            return self._create_success_result(f"文件创建成功: {file_path}")
            
        except Exception as e:
            return self._create_error_result(f"文件创建失败: {str(e)}")
    
    def _set_alarm(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """设置闹钟"""
        try:
            alarm_time = parameters.get("time", "")
            alarm_date = parameters.get("date", "")
            message = parameters.get("message", "闹钟提醒")
            repeat = parameters.get("repeat", False)
            
            if not alarm_time:
                return self._create_error_result("请指定闹钟时间")
            
            print(f"⏰ 设置闹钟: 时间={alarm_time}, 日期={alarm_date}, 消息={message}")
            
            # 根据系统类型调用不同的实现
            if self.system == "darwin":
                return self._set_alarm_macos(alarm_time, alarm_date, message, repeat)
            elif self.system == "windows":
                return self._set_alarm_windows(alarm_time, alarm_date, message, repeat)
            else:
                return self._set_alarm_linux(alarm_time, alarm_date, message, repeat)
                
        except Exception as e:
            return self._create_error_result(f"设置闹钟失败: {str(e)}")
    
    def _set_alarm_macos(self, alarm_time: str, alarm_date: str, message: str, repeat: bool) -> Dict[str, Any]:
        """在 macOS 上设置闹钟（使用提醒事项）"""
        try:
            from datetime import datetime, timedelta
            import re
            
            # 解析时间
            now = datetime.now()
            
            # 解析日期（如果提供）
            target_date = None
            if alarm_date:
                # 尝试解析日期格式
                date_patterns = [
                    (r"(\d{4})-(\d{1,2})-(\d{1,2})", "%Y-%m-%d"),
                    (r"(\d{1,2})月(\d{1,2})日", None),  # 特殊处理
                    (r"今天", "today"),
                    (r"明天", "tomorrow"),
                ]
                
                for pattern, fmt in date_patterns:
                    match = re.search(pattern, alarm_date)
                    if match:
                        if fmt == "today":
                            target_date = now.date()
                        elif fmt == "tomorrow":
                            target_date = (now + timedelta(days=1)).date()
                        elif fmt is None:  # X月X日格式
                            month = int(match.group(1))
                            day = int(match.group(2))
                            target_date = datetime(now.year, month, day).date()
                        else:
                            target_date = datetime.strptime(match.group(0), fmt).date()
                        break
            else:
                target_date = now.date()
            
            # 解析时间（支持中文自然语言）
            hour = None
            minute = 0
            
            # 🆕 中文数字转换
            chinese_numbers = {
                '零': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, 
                '六': 6, '七': 7, '八': 8, '九': 9, '十': 10,
                '十一': 11, '十二': 12, '两': 2
            }
            
            # 🆕 时段映射（早上、下午等）
            time_periods = {
                '凌晨': (0, 6),    # 0-6点
                '早上': (6, 12),   # 6-12点
                '上午': (6, 12),   # 6-12点
                '中午': (11, 13),  # 11-13点
                '下午': (12, 18),  # 12-18点
                '傍晚': (17, 19),  # 17-19点
                '晚上': (18, 24),  # 18-24点
                '晚': (18, 24),    # 18-24点
            }
            
            # 🆕 尝试解析自然语言时间（如"早上九点"、"下午三点半"）
            natural_time_pattern = r"(凌晨|早上|上午|中午|下午|傍晚|晚上|晚)?(.*?)点(.*?)分?"
            natural_match = re.search(natural_time_pattern, alarm_time)
            
            if natural_match:
                period = natural_match.group(1)  # 时段（早上、下午等）
                hour_str = natural_match.group(2).strip()  # 小时部分
                minute_str = natural_match.group(3).strip() if natural_match.group(3) else ''  # 分钟部分
                
                print(f"🔍 [时间解析] 时段={period}, 小时={hour_str}, 分钟={minute_str}")
                
                # 解析小时（支持中文数字）
                if hour_str:
                    # 先尝试中文数字转换
                    if hour_str in chinese_numbers:
                        hour = chinese_numbers[hour_str]
                    else:
                        # 尝试提取数字
                        hour_digits = re.search(r'\d+', hour_str)
                        if hour_digits:
                            hour = int(hour_digits.group())
                
                # 解析分钟（支持"半"、"一刻"等）
                if minute_str:
                    if '半' in minute_str:
                        minute = 30
                    elif '一刻' in minute_str or '十五' in minute_str:
                        minute = 15
                    elif '三刻' in minute_str or '四十五' in minute_str:
                        minute = 45
                    elif minute_str in chinese_numbers:
                        minute = chinese_numbers[minute_str]
                    else:
                        minute_digits = re.search(r'\d+', minute_str)
                        if minute_digits:
                            minute = int(minute_digits.group())
                
                # 根据时段调整小时（早上、下午转换为24小时制）
                if hour is not None and period:
                    period_range = time_periods.get(period)
                    if period_range:
                        min_hour, max_hour = period_range
                        # 如果是下午/晚上，且小时<12，加12转为24小时制
                        if period in ['下午', '傍晚', '晚上', '晚'] and hour < 12:
                            hour += 12
                        # 如果是凌晨，小时范围在0-6
                        elif period == '凌晨' and hour > 12:
                            hour = hour % 12  # 如果用户说"凌晨一点"，转为1点
                        # 如果是上午/早上，且说的是"十二点"，可能指中午12点
                        elif period in ['上午', '早上'] and hour == 12:
                            pass  # 保持12点
                        # 中午的特殊处理
                        elif period == '中午':
                            if hour < 11:
                                hour = 12  # "中午"通常指12点
                
                print(f"🔍 [时间解析] 解析结果: hour={hour}, minute={minute}")
            
            # 如果自然语言解析失败，尝试标准格式
            if hour is None:
                time_match = re.search(r"(\d{1,2}):(\d{2})|(\d{1,2})点(\d{1,2})?分?", alarm_time)
                if time_match:
                    if time_match.group(1):  # HH:MM 格式
                        hour = int(time_match.group(1))
                        minute = int(time_match.group(2))
                    else:  # X点X分格式
                        hour = int(time_match.group(3))
                        minute = int(time_match.group(4)) if time_match.group(4) else 0
            
            # 验证解析结果
            if hour is not None and 0 <= hour < 24 and 0 <= minute < 60:
                # 构建完整的闹钟时间
                alarm_datetime = datetime.combine(target_date, datetime.min.time())
                alarm_datetime = alarm_datetime.replace(hour=hour, minute=minute)
                
                # 如果时间已过，设置为明天
                if alarm_datetime <= now:
                    alarm_datetime += timedelta(days=1)
                # 格式化为 AppleScript 可用的格式
                alarm_str = alarm_datetime.strftime("%Y-%m-%d %H:%M:00")
                
                print(f"🔧 [调试] 解析后的闹钟时间: {alarm_str}")
                print(f"✅ [时间解析成功] {alarm_time} → {hour}:{minute:02d} (24小时制)")
                
                # 使用 AppleScript 创建提醒事项
                applescript = f'''
tell application "Reminders"
    activate
    
    -- 获取所有列表
    set allLists to every list
    
    -- 尝试找到"提醒事项"列表，如果不存在则创建
    set myList to missing value
    repeat with aList in allLists
        if name of aList is "提醒事项" then
            set myList to aList
            exit repeat
        end if
    end repeat
    
    -- 如果没有找到"提醒事项"列表，创建一个
    if myList is missing value then
        set myList to make new list with properties {{name:"提醒事项"}}
    end if
    
    -- 创建新的提醒事项
    tell myList
        set newReminder to make new reminder
        set name of newReminder to "{message}"
        set remind me date of newReminder to date "{alarm_str}"
        set body of newReminder to "语音助手设置的闹钟"
    end tell
    
    return "已设置闹钟: {alarm_datetime.strftime('%m月%d日 %H:%M')}"
end tell
'''
                
                # 执行 AppleScript 创建提醒事项
                print(f"🔧 [调试] 执行 AppleScript 创建提醒事项")
                result = subprocess.run(
                    ["osascript", "-e", applescript],
                    capture_output=True,
                    text=True,
                    timeout=10
                )
                
                if result.returncode == 0:
                    success_msg = f"⏰ 闹钟设置成功！\n"
                    success_msg += f"时间: {alarm_datetime.strftime('%Y年%m月%d日 %H:%M')}\n"
                    success_msg += f"消息: {message}\n"
                    success_msg += f"💡 已添加到「提醒事项」应用"
                    return self._create_success_result(success_msg)
                else:
                    error_msg = result.stderr.strip()
                    print(f"❌ [调试] AppleScript 执行失败: {error_msg}")
                    
                    # 降级方案：使用 osascript 显示对话框
                    fallback_msg = f"请在「提醒事项」中手动添加闹钟\n时间: {alarm_datetime.strftime('%Y年%m月%d日 %H:%M')}"
                    return self._create_error_result(fallback_msg)
            else:
                return self._create_error_result(f"无法解析时间格式: {alarm_time}")
                
        except Exception as e:
            print(f"❌ 设置 macOS 闹钟失败: {e}")
            return self._create_error_result(f"设置闹钟失败: {str(e)}")
    
    def _set_alarm_windows(self, alarm_time: str, alarm_date: str, message: str, repeat: bool) -> Dict[str, Any]:
        """在 Windows 上设置闹钟（使用任务计划程序）"""
        return self._create_success_result(f"Windows 闹钟功能正在开发中，时间: {alarm_time}")
    
    def _set_alarm_linux(self, alarm_time: str, alarm_date: str, message: str, repeat: bool) -> Dict[str, Any]:
        """在 Linux 上设置闹钟（使用 at 命令）"""
        return self._create_success_result(f"Linux 闹钟功能正在开发中，时间: {alarm_time}")
    
    def _list_alarms(self) -> Dict[str, Any]:
        """列出所有闹钟"""
        try:
            if self.system == "darwin":
                # 在 macOS 上列出提醒事项
                applescript = '''
tell application "Reminders"
    -- 获取所有列表
    set allLists to every list
    
    -- 尝试找到"提醒事项"列表
    set myList to missing value
    repeat with aList in allLists
        if name of aList is "提醒事项" then
            set myList to aList
            exit repeat
        end if
    end repeat
    
    -- 如果没有找到"提醒事项"列表，返回空
    if myList is missing value then
        return "没有找到「提醒事项」列表"
    end if
    
    set allReminders to reminders of myList
    set output to ""
    repeat with aReminder in allReminders
        set reminderName to name of aReminder
        try
            set reminderDate to remind me date of aReminder
            set output to output & reminderName & " - " & reminderDate & return
        end try
    end repeat
    
    if output is "" then
        return "「提醒事项」列表中没有闹钟"
    else
        return output
    end if
end tell
'''
                result = subprocess.run(
                    ["osascript", "-e", applescript],
                    capture_output=True,
                    text=True,
                    timeout=10
                )
                
                if result.returncode == 0:
                    reminders = result.stdout.strip()
                    if reminders:
                        return self._create_success_result(f"当前闹钟列表:\n{reminders}")
                    else:
                        return self._create_success_result("当前没有设置闹钟")
                else:
                    return self._create_error_result("无法获取闹钟列表")
            else:
                return self._create_success_result("该功能暂不支持当前操作系统")
                
        except Exception as e:
            return self._create_error_result(f"获取闹钟列表失败: {str(e)}")
    
    def _cancel_alarm(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """取消闹钟"""
        try:
            alarm_id = parameters.get("alarm_id", "")
            message = parameters.get("message", "")
            
            if self.system == "darwin":
                # 在 macOS 上删除提醒事项
                if message:
                    applescript = f'''
tell application "Reminders"
    -- 获取所有列表
    set allLists to every list
    
    -- 尝试找到"提醒事项"列表
    set myList to missing value
    repeat with aList in allLists
        if name of aList is "提醒事项" then
            set myList to aList
            exit repeat
        end if
    end repeat
    
    -- 如果没有找到"提醒事项"列表，返回错误
    if myList is missing value then
        return "没有找到「提醒事项」列表"
    end if
    
    set allReminders to reminders of myList
    repeat with aReminder in allReminders
        if name of aReminder is "{message}" then
            delete aReminder
            return "已取消闹钟: {message}"
        end if
    end repeat
    return "未找到指定的闹钟: {message}"
end tell
'''
                    result = subprocess.run(
                        ["osascript", "-e", applescript],
                        capture_output=True,
                        text=True,
                        timeout=10
                    )
                    
                    if result.returncode == 0:
                        return self._create_success_result(result.stdout.strip())
                    else:
                        return self._create_error_result("取消闹钟失败")
                else:
                    return self._create_error_result("请指定要取消的闹钟")
            else:
                return self._create_success_result("该功能暂不支持当前操作系统")
                
        except Exception as e:
            return self._create_error_result(f"取消闹钟失败: {str(e)}")
    
    def _execute_system_command(self, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """执行系统操作指令"""
        try:
            if action == "open_app":
                return self._open_application(parameters)
            elif action == "close_app":
                return self._close_application(parameters)
            else:
                return self._create_error_result(f"不支持的系统操作: {action}")
                
        except Exception as e:
            return self._create_error_result(f"系统操作失败: {str(e)}")
    
    def _execute_map_command(self, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """执行地图相关指令"""
        try:
            if not self.amap_handler.is_enabled():
                return self._create_error_result("地图服务未启用，请先配置高德地图API Key")
            
            # 调用地图命令处理器
            result = self.amap_handler.handle(action, parameters)
            
            # 转换结果格式以匹配CommandExecutor的格式
            if result['success']:
                return {
                    "success": True,
                    "message": result.get('voice_reply', result['message']),
                    "error": None,
                    "data": result.get('data')
                }
            else:
                return {
                    "success": False,
                    "message": None,
                    "error": result['message'],
                    "data": None
                }
                
        except Exception as e:
            return self._create_error_result(f"地图操作失败: {str(e)}")
    
    def _execute_ai_generation_command(self, action: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """执行AI内容生成指令"""
        try:
            if action == "write_novel":
                return self._generate_and_save_novel(parameters)
            elif action == "write_article":
                return self._generate_and_save_novel(parameters)
            else:
                return self._create_error_result(f"不支持的AI生成操作: {action}")
                
        except Exception as e:
            return self._create_error_result(f"AI生成操作失败: {str(e)}")
    
    def _open_file(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """打开文件"""
        try:
            file_path = parameters.get("file_path")
            if not file_path:
                return self._create_error_result("请指定文件路径")
            
            if not os.path.exists(file_path):
                return self._create_error_result(f"文件不存在: {file_path}")
            
            self._open_file_with_default_app(file_path)
            return self._create_success_result(f"文件打开成功: {file_path}")
            
        except Exception as e:
            return self._create_error_result(f"打开文件失败: {str(e)}")
    
    def _save_file(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """保存文件"""
        try:
            file_path = parameters.get("file_path")
            content = parameters.get("content", "")
            
            if not file_path:
                return self._create_error_result("请指定文件路径")
            
            # 确保目录存在
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
            
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)
            
            return self._create_success_result(f"文件保存成功: {file_path}")
            
        except Exception as e:
            return self._create_error_result(f"保存文件失败: {str(e)}")
    
    def _delete_file(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """删除文件"""
        try:
            file_path = parameters.get("file_path")
            if not file_path:
                return self._create_error_result("请指定文件路径")
            
            if not os.path.exists(file_path):
                return self._create_error_result(f"文件不存在: {file_path}")
            
            os.remove(file_path)
            return self._create_success_result(f"文件删除成功: {file_path}")
            
        except Exception as e:
            return self._create_error_result(f"删除文件失败: {str(e)}")
    
    def _open_application(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """打开应用程序"""
        try:
            app_name = parameters.get("app_name", "")
            
            # 尝试从映射中找到应用
            for category, apps in self.app_mappings.get(self.system, {}).items():
                if app_name in category or any(app_name.lower() in app.lower() for app in apps):
                    for app in apps:
                        if self._try_open_app(app):
                            return self._create_success_result(f"成功打开应用: {app}")
            
            # 直接尝试打开
            if self._try_open_app(app_name):
                return self._create_success_result(f"成功打开应用: {app_name}")
            
            return self._create_error_result(f"无法找到或打开应用: {app_name}")
            
        except Exception as e:
            return self._create_error_result(f"打开应用失败: {str(e)}")
    
    def _close_application(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """关闭应用程序"""
        try:
            app_name = parameters.get("app_name", "")
            
            if self.system == "darwin":
                cmd = ["osascript", "-e", f'tell application "{app_name}" to quit']
                subprocess.run(cmd, check=True, timeout=5)
            elif self.system == "windows":
                cmd = ["taskkill", "/f", "/im", f"{app_name}.exe"]
                subprocess.run(cmd, check=True, timeout=5)
            else:
                cmd = ["pkill", app_name]
                subprocess.run(cmd, check=True, timeout=5)
            
            return self._create_success_result(f"成功关闭应用: {app_name}")
            
        except Exception as e:
            return self._create_error_result(f"关闭应用失败: {str(e)}")
    
    def _generate_and_save_novel(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """生成小说并保存"""
        try:
            topic = parameters.get("topic", "小说")
            length = parameters.get("length", "短篇")
            style = parameters.get("style", "现代")
            
            # 构建生成小说的提示词
            prompt = f"""请写一篇{length}{style}小说，主题是：{topic}

要求：
1. 情节完整，有开头、发展、高潮、结尾
2. 人物形象鲜明
3. 语言流畅，描写生动
4. ⚠️ 字数控制在200-300字以内（因为需要语音播报）
5. 内容精炼，每句话都要有价值

请直接开始写作，不要包含任何解释文字："""
            
            print("📝 正在生成小说内容...")
            
            # 调用大模型生成小说 - 增加超时处理和重试机制
            max_retries = 2
            retry_count = 0
            novel_content = None
            
            while retry_count < max_retries and not novel_content:
                try:
                    print(f"   尝试生成内容 (第{retry_count + 1}次)...")
                    novel_content = self.llm_client.chat(
                        user_input=prompt,
                        system_prompt="你是一位优秀的小说家，擅长创作精炼简短的小说。请创作200-300字的高质量小说，内容要精炼有趣，适合语音播报。",
                        max_tokens=300,  # 减少token数量，控制生成长度
                        temperature=0.8
                    )
                    if novel_content:
                        break
                except Exception as e:
                    print(f"   第{retry_count + 1}次生成失败: {str(e)}")
                    retry_count += 1
                    if retry_count < max_retries:
                        print(f"   等待3秒后重试...")
                        time.sleep(3)
            
            if not novel_content:
                return self._create_error_result("小说生成失败")
            
            # 保存到文件
            desktop = os.path.join(os.path.expanduser("~"), "Desktop")
            file_name = f"AI生成小说_{topic}_{length}.txt"
            file_path = os.path.join(desktop, file_name)
            
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(f"标题：{topic}\n")
                f.write(f"类型：{length}{style}小说\n")
                f.write(f"生成时间：{self._get_current_time()}\n")
                f.write("=" * 50 + "\n\n")
                f.write(novel_content)
            
            # 打开文件
            self._open_file_with_default_app(file_path)
            
            return self._create_success_result(f"小说生成并保存成功: {file_path}")
            
        except Exception as e:
            return self._create_error_result(f"小说生成失败: {str(e)}")
    
    def _try_open_app(self, app_name: str) -> bool:
        """尝试打开应用程序"""
        try:
            if self.system == "darwin":
                cmd = ["open", "-a", app_name]
                print(f"🔧 [调试] 尝试打开应用: {' '.join(cmd)}")
                subprocess.run(cmd, check=True, timeout=5)
            elif self.system == "windows":
                cmd = ["start", app_name]
                print(f"🔧 [调试] 尝试打开应用: {' '.join(cmd)} (shell=True)")
                subprocess.run(cmd, shell=True, check=True, timeout=5)
            else:
                cmd = [app_name]
                print(f"🔧 [调试] 尝试打开应用: {' '.join(cmd)}")
                subprocess.run(cmd, check=True, timeout=5)
            print(f"✅ [调试] 成功打开: {app_name}")
            return True
        except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError) as e:
            print(f"❌ [调试] 打开失败: {app_name}, 错误: {e}")
            return False
    
    def _open_file_with_default_app(self, file_path: str):
        """使用默认应用打开文件"""
        try:
            if self.system == "darwin":
                cmd = ["open", file_path]
                print(f"🔧 [调试] 打开文件: {' '.join(cmd)}")
                subprocess.run(cmd)
            elif self.system == "windows":
                cmd = ["start", file_path]
                print(f"🔧 [调试] 打开文件: {' '.join(cmd)} (shell=True)")
                subprocess.run(cmd, shell=True)
            else:
                cmd = ["xdg-open", file_path]
                print(f"🔧 [调试] 打开文件: {' '.join(cmd)}")
                subprocess.run(cmd)
            print(f"✅ [调试] 文件已打开: {file_path}")
        except Exception as e:
            print(f"⚠️ 无法自动打开文件: {e}")
    
    def _get_current_time(self) -> str:
        """获取当前时间字符串"""
        from datetime import datetime
        return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    def _create_success_result(self, message: str) -> Dict[str, Any]:
        """创建成功结果"""
        return {
            "success": True,
            "message": message,
            "error": None
        }
    
    def _create_error_result(self, error_message: str) -> Dict[str, Any]:
        """创建错误结果"""
        return {
            "success": False,
            "message": None,
            "error": error_message
        }


def main():
    """测试函数"""
    executor = CommandExecutor()
    
    # 测试用例
    test_commands = [
        {
            "intent": "music",
            "action": "play",
            "parameters": {"song_name": "稻香", "artist": "周杰伦"},
            "confidence": 0.95,
            "description": "播放周杰伦的稻香"
        },
        {
            "intent": "ai_generation",
            "action": "write_novel",
            "parameters": {"topic": "科幻冒险", "length": "短篇", "style": "现代"},
            "confidence": 0.9,
            "description": "写一篇科幻冒险小说"
        },
        {
            "intent": "system",
            "action": "open_app",
            "parameters": {"app_name": "文本编辑器"},
            "confidence": 0.85,
            "description": "打开文本编辑器"
        },
        {
            "intent": "alarm",
            "action": "set",
            "parameters": {"time": "明天早上8点", "message": "起床闹钟"},
            "confidence": 0.9,
            "description": "设置明天早上8点的闹钟"
        }
    ]
    
    print("🧪 开始测试指令执行...")
    print("=" * 50)
    
    for i, command in enumerate(test_commands, 1):
        print(f"\n测试 {i}: {command['description']}")
        result = executor.execute_command(command)
        print(f"结果: {json.dumps(result, ensure_ascii=False, indent=2)}")
        print("-" * 30)


if __name__ == "__main__":
    main()
